package com.vadmin.vadminjava.service;

import cn.hutool.core.math.Money;
import com.alibaba.fastjson.JSONObject;
import com.vadmin.vadminjava.common.*;
import com.vadmin.vadminjava.db.DBUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


import static com.vadmin.vadminjava.common.CommonUtils.getTimesMillisIncrease;
import static com.vadmin.vadminjava.common.CommonUtils.stringToArray;

/* ***********************************************************
 *
 * 企业微信客户端的相关实现
 *
 * **********************************************************/
@Component
public class WxWorkClientService {

	org.slf4j.Logger logger = LoggerFactory.getLogger(WxWorkClientService.class.getName());

	@Autowired
	WxWorkCommon wxWorkCommon;
	@Autowired
	AdminLogService adminLogService;

	@Autowired
	WxUserMoneyService wxUserMoneyService;


	/**
	 * 职员登录（请求用户身份）
	 * 2022-02-18 经测试通过
	 * 2022-03-01 经测试，如果不是外部客户的微信用户登录，不会有external_userid字段
	 * https://developer.work.weixin.qq.com/document/path/91023
	 * @param params
	 * @return
	 */
	public JSONObject workerLogin(JSONObject params){
		//初始
		JSONObject map = new JSONObject();
		map.put("resultFlag", false);
		map.put("resultMsg", "操作失败");
		//jwt
		JSONObject _jwt = new JSONObject();

		try {
			//获取参数
			String code = params.getString("code");//官方：code只能使用一次，5分钟未被使用自动过期。

			//获取accessToken
			String accessToken = wxWorkCommon.getAccessToken();

			//拼凑url（请求用户身份数据的）
			String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token="+accessToken+"&code="+code;
			//请求
			JSONObject data = JSONObject.parseObject(HttpUtils.doGet(url));

			//龙用企业微信： { "errcode": 0, "UserId": "YangZhiCong", "DeviceId": "aaef58ca-9718-48da-98aa-6c5320754543", "errmsg": "ok" }
			// 黄浮驴是外部客户时，用微信登录 这里这个external_userid和用户添加删除时那个external_userid是一样的
			// { "errcode": 0, "external_userid": "wmJRSsWwAA4c4EdckQvJsNqwKNOj7O6g", "DeviceId": "7d8f23223f6d585c70de57d20c8d1571", "errmsg": "ok", "OpenId": "oM9JCwt-elYJ6EghJnODE0a1wGlg" }
			//黄浮驴不是外部客户时：，就没有external_userid了，但OpenId是一样的
			//{ "errcode": 0, "DeviceId": "7d8f23223f6d585c70de57d20c8d1571", "errmsg": "ok", "OpenId": "oM9JCwt-elYJ6EghJnODE0a1wGlg" }

			String UserId = data.getString("UserId");//用户id
			String externalUserid = data.getString("external_userid");//外部用户id

			//得到数据时才处理
			if(data.isEmpty()){
				map.put("resultFlag", false);
				map.put("resultMsg", "获取访问客户数据失败");
			}else{
				logger.info("进行了登录处理，返回数据：{}",data);

				//判断
				if(StringUtils.isEmpty(UserId) && StringUtils.isEmpty(externalUserid)){//如果2种id都没有，说明是普通微信打开
					map.put("data", null);
					map.put("token", "");
					map.put("resultFlag", false);
					map.put("resultMsg", "登录失败");
				}else{
					if(StringUtils.isNotEmpty(UserId)){ //员工
						_jwt.put("userId",UserId);
						workerUserDataHandler(UserId);//员工数据处理

					}else if(StringUtils.isNotEmpty(externalUserid)){ // 如果是外部客户，才处理
						_jwt.put("externalUserid",data.getString("external_userid"));
						//注意，下面的逻辑应该用不上
						// 因为只有成为外部客户登录时，才有external_userid, 而且添加为外部客户时，肯定已经先写入数据了
						externalUserDataHandler(externalUserid);//进行外部客户数据处理
					}
					_jwt.put("expiresTime",getTimesMillisIncrease(30));//todo 这个过期是怎么用？？？
					//输出
					map.put("data", data);//返回用户信息
					map.put("token", JwtUtil.sign(_jwt.toJSONString())); //jwt token
					map.put("resultFlag", true);
					map.put("resultMsg", "登录成功");
				}

			}

		} catch (Exception ex) {
			logger.warn("员工登录不知为什么出错了他妈{}",ex);
		} finally {

		}

		return map;
	}


	/**
	 * 员工登录后的数据处理
	 * @param userData
	 */
	public void workerUserDataHandler(String userId){
		//参数
		DBUtil dbUtil = new DBUtil();

		try {
			//判断是否已经有数据
			String sql = "select count(id) as count1 from wxwork_user where user_id='"+userId+"'";//获取行数
			Integer count = ResultSetToJavaBean.copyJsonSingleQuery(dbUtil, sql).getInteger("count1");
			//判断是否存在数据
			if(count==0){
				logger.info("登录处理>>>>没有这个员工{}，创建了员工数据",userId);

				//http get获取员工数据
				JSONObject _data = wxWorkCommon.getUserDataByHttp(userId).getJSONObject("data");
				//System.out.println("当前员工详情"+_data);
				String name            = _data.getString("name"); //'员工姓名',
				String mobile          = _data.getString("mobile"); //'手机',
				String department      = _data.getString("department").replaceAll("[\\[\\]]",""); //'成员所属部门id列表',
				String position        = _data.getString("position"); //'职务信息',
				String gender          = _data.getString("gender"); //'性别',
				String avatar          = _data.getString("avatar"); //'头像',
				String mainDepartment = _data.getString("main_department"); //'主部门，仅当应用对主部门有查看权限时返回。',

				//写入数据库
				String sqlInserUer = "INSERT INTO `wxwork_user`( `user_id`, `name`,`mobile`, `department`, `position`, `gender`, `avatar`, `main_department`,`update_time`) " +
						"VALUES ('"+userId+"', '"+name+"', '"+mobile+"','"+department+"', '"+position+"', '"+gender+"', '"+avatar+"', '"+mainDepartment+"',NOW())";
				//System.out.println("员工数据sql："+sqlInserUer);
				dbUtil.insertOrUpdateInfoTONum(sqlInserUer);

			}else{
				//System.out.println("已经有这个员工，不重复写入数据");
			}
		} catch (Exception ex) {
			logger.error("workerUserDataHandler处理出错了",ex);
		} finally {
			dbUtil.closeNoErr();
		}
	}


	/**
	 * 外部客户登录后的数据处理
	 * 2022-03-01 经测试，如果不是外部客户，是不会有external_userid的
	 * @param ExternalUserID
	 */
	public void externalUserDataHandler(String ExternalUserID){
		//参数
		DBUtil dbUtil = new DBUtil();

		try {
			//获得当前条件记录数
			String sql = "select count(id) as count1 from wxwork_external_user where external_userid='"+ExternalUserID+"'";//获取行数
			Integer count = ResultSetToJavaBean.copyJsonSingleQuery(dbUtil, sql).getInteger("count1");

			//判断是否存在数据，没有就写入
			if(count==0){
				logger.info("没有这个外部用户的数据{}，写入数据库",ExternalUserID);
				JSONObject _data = wxWorkCommon.getExternalUserDataByHttp(ExternalUserID).getJSONObject("data");
				wxWorkCommon.insertExternalUserData(_data);
			}else{
				//System.out.println("已经有这个外部客户数据，不重复写入数据");
			}
		} catch (Exception ex) {

		} finally {
			dbUtil.closeNoErr();
		}
	}


	/**
	 * 关联外部客户与openId
	 * 这个关联应该是用来卡券领取或核销时用的，通过openid关联到外部客户，关联到员工，给员工发佣金
	 * @param params
	 * @return
	 */
	public JSONObject bindExternalUserToWxUser(JSONObject params){
		//初始
		DBUtil dbUtil = new DBUtil();
		JSONObject map = new JSONObject();
		map.put("resultFlag", false);
		map.put("resultMsg", "操作失败");
		String log = "";

		//参数
		String _externalUserid = params.getString("externalUserid");
		String _openId = params.getString("openId");

		if(StringUtils.isEmpty(_externalUserid) || StringUtils.isEmpty(_openId)){
			String tip = "";
			if(StringUtils.isEmpty(_openId)) tip += ",缺少openId";
			if(StringUtils.isEmpty(_externalUserid)) tip += "缺少externalUserId";
			map.put("resultFlag", false);
			map.put("resultMsg", "绑定openid>缺少必要参数:"+tip);
			return map;
		}
		//数据库处理
		try {
			//查询是否有存在数据
			String sql = "select count(id) as count1 from wx_user_relation where external_userid = '"+_externalUserid+"'";//获取行数
			Integer count = ResultSetToJavaBean.copyJsonSingleQuery(dbUtil, sql).getInteger("count1");//获取行数
			if(count==0){ // 不存在就写入
				String sqlR = "INSERT INTO `wx_user_relation`(`open_id`, `external_userid`, `create_time`) VALUES ('"+_openId+"', '"+_externalUserid+"', NOW())";
				dbUtil.insertOrUpdateInfoTONum(sqlR);
				map.put("resultFlag", true);
				map.put("resultMsg", "成功关联openId");
				log = "成功关联了外部客户"+_externalUserid+"的openId"+_openId;
				logger.info(log);
				adminLogService.write(LogEnum.EVENT_BIND_OPENID.getName(),LogEnum.EVENT_BIND_OPENID.getIndex(),log);

			}else{
				map.put("resultFlag", false);
				map.put("resultMsg", "已经存在这个外部用户的openid关联数据");
				logger.info("已经存在外部客户：{} 的openid关联数据",_externalUserid);
			}
		} catch (Exception ex) {
			logger.error("bindExternalUserToWxUser处理出错了",ex);
		} finally {
			dbUtil.closeNoErr();
		}



		return map;
	}


	/**
	 * 外部客户查看优惠券事件（只是查看，领取是另一个处理方法）
	 * 主要是佣金发放	 * 使用事务处理，出错则回滚
	 * 2022-03-27 测试通过
	 * 2022-06-04 经讨论，发券不给员工分佣金。
	 * @param params
	 * @return
	 */
	public JSONObject showCouponEvent(JSONObject params){
		//初始
		DBUtil dbUtil = new DBUtil();
		JSONObject map = new JSONObject();
		map.put("resultFlag", false);
		map.put("resultMsg", "操作失败");
		String log = "";

		//参数
		String _couponId = params.getString("couponId");//卡券id
		String _referrer = params.getString("referrer");//推荐人
		String _externalUserid = params.getString("externalUserid");//客户
		String _openId = params.getString("openId");//

		//参数限制
		if(
			 StringUtils.isEmpty(_couponId)
				|| StringUtils.isEmpty(_externalUserid)
				|| StringUtils.isEmpty(_openId)
				|| StringUtils.isEmpty(_referrer)
		){
			String tip = "";
			if(StringUtils.isEmpty(_couponId)) tip += "缺少couponId";
			if(StringUtils.isEmpty(_externalUserid)) tip += "缺少externalUserId";
			if(StringUtils.isEmpty(_referrer)) tip += "缺少referrer";
			if(StringUtils.isEmpty(_openId)) tip += ",缺少openId";

			map.put("resultFlag", false);
			map.put("resultMsg", "领券事件接口>缺少必要参数:"+tip);
			return map;
		}

		//系统日志
		log = "客户："+_externalUserid+"查看了优惠券："+_couponId+"，所属员工："+_referrer;
		logger.info(log);
		adminLogService.write(LogEnum.COUPON_SHOW.name,LogEnum.COUPON_SHOW.index,log);

		//2022-06-04 经讨论，发券不给员工分佣金。
		/*//数据库处理
		try {
			dbUtil.conn.setAutoCommit(false);//不自动提交

			//查询是否有存在数据，这里要注意类型，券码，客户
			String sql = "select count(id) as count1 " +
					"from wxwork_user_money_log " +
					"where coupon_id = '"+_couponId+"' and external_userid = '"+_externalUserid+"' and  event_code='"+ MoneyLogEnum.COUPON_SHOW.code+"'";//获取行数
			//System.out.println("查询是否已存在分佣明细"+sql);
			Integer count = ResultSetToJavaBean.copyJsonSingleQuery(dbUtil, sql).getInteger("count1");//获取行数


			//如果没有记录
			if(count==0){

				//操作资金数
				String _amount = WxWorkConfig.COMMISSION_SHOW.toString();

				//数据准备
				String sql2 = "select * from wxwork_user where user_id = '" + _referrer + "'";
				Double _money = ResultSetToJavaBean.copyJsonSingleQuery(dbUtil, sql2).getDouble("money");
				String _moneyAfter = BigDecimalUtils.add(_money,_amount).toString();

				//在这个位置更新员工资金
				wxUserMoneyService.userMoneyChange(dbUtil,_referrer,_amount);//写入

				//记录明细
				JSONObject logParams = new JSONObject();
				logParams.put("user_id",_referrer);
				logParams.put("external_userid",_externalUserid);
				logParams.put("open_id",_openId);
				logParams.put("money_before",_money);
				logParams.put("money",_amount);
				logParams.put("money_after",_moneyAfter);
				logParams.put("coupon_id",_couponId);//
				logParams.put("coupon_code","");//客户打开优惠券时，没有这个数据，因为还没有领取就要先分佣给员工
				logParams.put("event",MoneyLogEnum.COUPON_SHOW.name);
				logParams.put("event_code",MoneyLogEnum.COUPON_SHOW.code);
				logParams.put("type",MoneyLogEnum.TYPE_ADD.name);
				logParams.put("type_code",MoneyLogEnum.TYPE_ADD.code);
				logParams.put("remark","进行了首次查看优惠券分佣,coupon_id:"+_couponId);
				wxUserMoneyService.userMoneyLog(dbUtil,logParams);//写入

				//系统日志,不里不参与事务回滚
				log = "客户："+_externalUserid+"首次成功查看了优惠券："+_couponId+"，给员工："+_referrer+"成功进行分佣";
				adminLogService.write(LogEnum.COUPON_SHOW.name,LogEnum.COUPON_SHOW.index,log);

				//最后处理
				dbUtil.conn.commit();
				map.put("resultFlag", true);
				map.put("resultMsg", "成功处理了发券事件");
				logger.info(log);

			}else{
				map.put("resultFlag", false);
				map.put("resultMsg", "已存在同一个客户同个优惠券分佣");
				logger.info("已存在客户{}对这个优惠券{} 的{}事件分佣明细",_externalUserid,_couponId,MoneyLogEnum.COUPON_SHOW.name);
			}


		} catch (Exception ex) {
			logger.error("外部客户查看优惠券事件处理过程出错了{}",ex);
			try {
				dbUtil.conn.rollback();
			} catch (Exception e) {

			}

		} finally {
			dbUtil.closeNoErr();
		}*/



		return map;
	}

}
